﻿using System;
using System.Collections.Generic;
using System.Text;
using Vortex.Drawing;

namespace Vortex.SceneFramework.Effects {

	/// <summary>
	/// Implementation of <see cref="ISceneSwitchEffectContext"/> for domain graph subsystem
	/// </summary>
	public class SceneSwitchEffectPlayer : ISceneSwitchContext, IDisposable {
		private ISceneSwitchEffect _switchEffect;
		private BaseTexture _newSceneTexture;
		private BaseTexture _oldSceneTexture;
		private float _totalEffectTime;
		private float _invertedTotalEffectTime;
		private float _ellapsedTime = 0;

		/// <summary>
		/// Initializes a new instance of the <see cref="SceneSwitchEffectContext"/> class.
		/// </summary>
		/// <param name="newSceneSprite">The new domain sprite.</param>
		/// <param name="oldSceneSprite">The old domain sprite.</param>
		/// <param name="totalEffectTime">The total effect time.</param>
		public SceneSwitchEffectPlayer(ISceneSwitchEffect switchEffect, float totalEffectTime, BaseTexture newSceneTexture, BaseTexture oldSceneTexture) {
			if (null == switchEffect) throw new ArgumentNullException("switchEffect");
			if (null == newSceneTexture) throw new ArgumentNullException("newSceneTexture");
			if (null == oldSceneTexture) throw new ArgumentNullException("oldSceneTexture");

			_switchEffect = switchEffect;
			_newSceneTexture = newSceneTexture;
			_oldSceneTexture = oldSceneTexture;
			_totalEffectTime = totalEffectTime;
			_invertedTotalEffectTime = 1 / totalEffectTime;

			//invoke effect begin
			switchEffect.BeginEffect(this);
		}

		/// <summary>
		/// Updates the context with the specified delta time.
		/// </summary>
		/// <param name="deltaTime">The delta time.</param>
		/// <returns><c>true</c> if effect can be continued; otherwise <c>false</c></returns>
		public bool Update(float deltaTime) {
			_ellapsedTime += deltaTime;
			if (_ellapsedTime < _totalEffectTime) {
				_switchEffect.Update(deltaTime);
				return true;
			} else {
				return false;
			}
		}

		/// <summary>
		/// Draws the specified effect on a target.
		/// </summary>
		/// <param name="canvas">The canvas.</param>
		public void Draw(Canvas2D canvas) {
			//resend to effect...
			_switchEffect.Draw(canvas);
		}

		#region ISceneSwitchContext Members

		/// <summary>
		/// Gets the new domain sprite.
		/// </summary>
		/// <value>The new domain sprite.</value>
		public Sprite NewSceneSprite {
			get { return _newSceneTexture.ToSprite(); }
		}

		/// <summary>
		/// Gets the old domain sprite.
		/// </summary>
		/// <value>The old domain sprite.</value>
		public Sprite OldSceneSprite {
			get { return _oldSceneTexture.ToSprite(); }
		}

		/// <summary>
		/// Gets the total effect time.
		/// </summary>
		/// <value>The total effect time.</value>
		public float TotalEffectTime {
			get { return _totalEffectTime; }
		}

		/// <summary>
		/// Gets the effect ellapsed time.
		/// </summary>
		/// <value>The effect ellapsed time.</value>
		public float EllapsedTime {
			get { return _ellapsedTime; }
		}

		/// <summary>
		/// Gets the progress of effect.
		/// </summary>
		/// <value>The effect progress. Value in range 0..1.</value>
		public float Progress {
			get { return _ellapsedTime * _invertedTotalEffectTime; }
		}

		#endregion

		#region IDisposable Members

		/// <summary>
		/// Ends the effect playing
		/// </summary>
		public void Dispose() {
			_switchEffect.EndEffect();
		}

		#endregion
	}
}
